package trader.orig;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class Trader {
    public static void main(String[] args) throws Exception {
        //if (args.length == 1) {
        //    System.out.println(new Trader()sha1(args[0]));
        //    return;
        //}
        new Trader().run();
    }
    
    public void run() throws Exception {
        if (!Util.login(Util.MAIL, Util.PASSWORD)) {
            System.out.println("Failed to login");
            return;
        }
        getPortfolioContent();
        readLimits();
        
        System.out.println("Launching with: ");
        for (String id : Util.limits.keySet()) {
            System.out.println(id + " : " + Util.limits.get(id));
        }
        
        startPollers();
        logic();
    }
    
    public void readLimits() {
        try {
            BufferedReader in = new BufferedReader(new FileReader("limits"));
            String line = "";
            while ((line = in.readLine()) != null) {
                if (line.startsWith("#") || line.equals("")) {
                    continue;
                }
                String[] ss = line.split(" ");
                
                String id = ss[0];
                Limit.Type type = Limit.Type.valueOf(ss[1]);
                String s = ss[2];
                double lim = Double.parseDouble(ss[3]);
                Limit limit = Util.limits.get(id);
                if (limit == null) {
                    limit = new Limit();
                }
                if (s.equals("low")) {
                    limit.lowerLim = lim;
                    limit.lowerType = type;
                } else if (s.equals("high")) {
                    limit.upperLim = lim;
                    limit.upperType = type;
                } else {
                    new Exception().printStackTrace();
                    System.exit(0);
                }
                
                if(ss.length == 6) {
                    limit.buyAmount = Double.parseDouble(ss[4]);
                    limit.portfolio = Integer.parseInt(ss[5]);
                    Util.sought.put(id, new SoughtInstrument("", id));
                }
                Util.limits.put(id, limit);
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(0);
        }
    }
    
    private void startPollers() {
        for (String id : Util.portfolio.keySet()) {
            Poller p = new Poller(id);
            Util.pollers.put(id, p);
            new Thread(p).start();
        }
        
        for (String id : Util.sought.keySet()) {
            Poller p = new Poller(id, true);
            Util.pollers.put(id, p);
            new Thread(p).start();
        }
    }
    
    public void logic() throws Exception {
        int i = 0;
        while (true) {
            for (Map.Entry<String, OwnedInstrument> entry : Util.portfolio.entrySet()) {
                OwnedInstrument owned = entry.getValue();
                if (owned.getBuy() == 0) {
                    continue;
                }
                String id = entry.getKey();
                Limit lim = Util.limits.get(id);
                if (lim == null) {
                    continue;
                }
                if (i % 60 == 0) {
                    System.out.println("Comparing " + owned.id() + " (owned) actual=" + owned.getBuy() + " lower=" + lim.lowerLim + ", upper=" + lim.upperLim);
                }
                if (owned.getBuy() <= lim.lowerLim) {
                    if (lim.lowerType == Limit.Type.SELL) {
                        System.out.println("Lower limit reached, selling: symbol=" + owned.symbol() + ", limit=" + lim.lowerLim + ", value=" + owned.getBuy());
                        boolean res = Util.sell(id, owned.internalId(), owned.getBuy(), owned.getVolume());
                        System.out.println("Sell " + (res ? "successful" : "failed"));
                        Util.limits.remove(id);
                    } else {
                        System.out.println("Lower limit reached, buying NYI");
                    }
                }
                if (owned.getBuy() >= lim.upperLim) {
                    if (lim.upperType == Limit.Type.SELL) {
                        System.out.println("Upper limit reached, selling: symbol=" + owned.symbol() + ", limit=" + lim.upperLim + ", value=" + owned.getBuy());
                        boolean res = Util.sell(id, owned.internalId(), owned.getBuy(), owned.getVolume());
                        System.out.println("Sell " + (res ? "successful" : "failed"));
                        Util.limits.remove(id);
                    } else {
                        System.out.println("Upper limit reached, buying NYI");
                    }
                }
            }
            
            for (Map.Entry<String, SoughtInstrument> entry : Util.sought.entrySet()) {
                SoughtInstrument sought = entry.getValue();
                String id = entry.getKey();
                Limit lim = Util.limits.get(id);
                if (lim == null) {
                    continue;
                }
                if (i++ % 60 == 0) {
                    System.out.println("Comparing " + sought.id() + " (sought) actual=" + sought.getSell() + " lower=" + lim.lowerLim + ", upper=" + lim.upperLim);
                }
                if (sought.getSell() <= lim.lowerLim) {
                    if (lim.lowerType == Limit.Type.BUY) {
                        int amount = (int)lim.buyAmount;
                        amount /= sought.getSell();
                        System.out.println("Lower limit reached, buying: id=" + sought.id() + ", limit=" + lim.lowerLim + ", value=" + sought.getSell() + ", amount=" + amount);
                        boolean res = Util.buy(id, sought.getSell(), amount, lim.portfolio);
                        System.out.println("Buy: " + (res ? "successful" : "failed"));
                        Util.limits.remove(id);
                        Util.sought.remove(id);
                        
                        //TODO
                        System.out.println("Restart...");
                        System.exit(0);
                        //Util.portfolio.put(id, new OwnedInstrument()) //TODO
                    } else {
                        System.out.println("Having a SELL limit on a sought instrument makes no sense. Really.");
                    }
                }
            }
            i++;
            
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    private void getPortfolioContent() {
        try {
            for (int i = 0; i < Util.PORTFOLIOS.length; ++i) {
                URL url = new URL(Util.BASE_URL + "/scripts/php/data/getdata.php");
                HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                String data = "action=get_portfolio_content&portfolio_id=" + Util.PORTFOLIOS[i];
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Cookie", Util.sessionId);
                conn.setDoOutput(true);
                OutputStream out = conn.getOutputStream();
                out.write(data.getBytes());
                out.close();
                String line = "";
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                while ((line = in.readLine()) != null) {
                    if (line.equals("")) {
                        continue;
                    }
                    //System.out.println("line: " + line);
                    Object obj = Util.fromJSon(line);
                    if (obj instanceof JSONObject) {
                        JSONObject jsonObj = (JSONObject)obj;
                        JSONObject content = (JSONObject)jsonObj.get("content");
                        for (Object o : content.keySet()) {
                            JSONObject jsonInstr = (JSONObject)content.get(o);
                            String id = (String)jsonInstr.get("instrument_id");
                            OwnedInstrument instr = new OwnedInstrument((String)jsonInstr.get("instrument_symbol"), id, (String)o);
                            Util.portfolio.put(id, instr);
                            instr.setVolume(Integer.parseInt((String)jsonInstr.get("volume")));
                        }
                    } else if (obj instanceof JSONArray) {
                        //Nothing in portfolio
                    } else {
                        System.out.println("What is this? " + obj.getClass() + " : line");
                    }
                }
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(0);
        }
    }
}
